package com.uuah.server.context.notification;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.uuah.server.api.context.notification.linstener.IServerNotificationListener;
import com.uuah.server.config.i18n.ServerMessages;

class EventConfiguration {

	protected transient Logger logger = LoggerFactory
			.getLogger(EventConfiguration.class);
	private Map interfaceToTypes = new HashMap();
	private Set listenerSubscriptionPairs = new HashSet();

	private boolean dirty = true;
	private EventPolicy policy;

	synchronized void addInterfaceToType(Class iface, Class type) {
		dirty = true;
		if (!ServerNotification.class.isAssignableFrom(type)) {
			throw new IllegalArgumentException(ServerMessages
					.propertyIsNotSupportedType("type",
							ServerNotification.class, type).getMessage());
		}
		if (!interfaceToTypes.containsKey(iface)) {
			interfaceToTypes.put(iface, new HashSet());
		}
		Set events = (Set) interfaceToTypes.get(iface);
		events.add(type);
		if (logger.isDebugEnabled()) {
			logger.debug("Register Event Type: " + type);
			logger.debug("Register Interface '" + iface + "' to Type: '"
					+ type + "'");
		}
	}

	synchronized void addAllInterfaceToTypes(Map interfaceToTypes)
			throws ClassNotFoundException {
		dirty = true;
		for (Iterator ifaces = interfaceToTypes.keySet().iterator(); ifaces
				.hasNext();) {
			Object iface = ifaces.next();
			addInterfaceToType(ServerNotificationManager.toClass(iface),
					ServerNotificationManager.toClass(interfaceToTypes
							.get(iface)));
		}
	}

	synchronized void addListenerSubscriptionPair(ListenerSubscriptionPair pair) {
		dirty = true;
		listenerSubscriptionPairs.add(pair);
	}

	synchronized void removeListener(IServerNotificationListener listener) {
		dirty = true;
		Set toRemove = new HashSet();
		for (Iterator listeners = listenerSubscriptionPairs.iterator(); listeners
				.hasNext();) {
			ListenerSubscriptionPair pair = (ListenerSubscriptionPair) listeners
					.next();
			if (pair.getListener().equals(listener)) {
				toRemove.add(pair);
			}
		}
		listenerSubscriptionPairs.removeAll(toRemove);
	}

	synchronized void removeAllListeners(Collection listeners) {
		dirty = true;
		for (Iterator listener = listeners.iterator(); listener.hasNext();) {
			removeListener((IServerNotificationListener) listener.next());
		}
	}

	synchronized EventPolicy getPolicy() {
		if (dirty) {
			policy = new EventPolicy(interfaceToTypes,
					listenerSubscriptionPairs);
			dirty = false;
		}
		return policy;
	}
}
